import json
import os
import pprint
import gzip
from git import Repo
from argparse import ArgumentParser


def preprocess(dict_data, i = 5):
    MAX_N = 10
    word_pos_list = {
        "a.": [set() for _ in range(MAX_N)],
        "v.": [set() for _ in range(MAX_N)],
        "n.": [set() for _ in range(MAX_N)],
    }
    for entry in dict_data:
        if entry['pos'] not in word_pos_list:
            continue
        N = min(len(entry['word']), MAX_N)
        word_pos_list[entry['pos']][N-1].add(entry['word'])

    word_pos_i = {
        "a.": (sorted(list(word_pos_list['a.'][i])), len(word_pos_list['a.'][i])),
        "v.": (sorted(list(word_pos_list['v.'][i])), len(word_pos_list['v.'][i])),
        "n.": (sorted(list(word_pos_list['n.'][i])), len(word_pos_list['n.'][i])),
    }
    return word_pos_i


def compute_fancy_name(word_pos_i, hash=None):

    if hash is None:
        repo = Repo('.')
        hash = repo.head.commit.hexsha

    iadj = int(hash[:10], 16)
    iverb = int(hash[10:20], 16)

    adj:str = word_pos_i['a.'][0][iadj % word_pos_i['a.'][1]]
    verb:str = word_pos_i['v.'][0][iverb % word_pos_i['v.'][1]]
    noun:str = word_pos_i['n.'][0][int(hash[20:], 16) % word_pos_i['n.'][1]]

    if iadj > iverb:
        first = adj
        fancy_name = adj[0].upper() + adj[1:].lower() + noun[0].upper() + noun[1:].lower()
    else:
        first = verb
        fancy_name = verb[0].upper() + verb[1:].lower() + noun[0].upper() + noun[1:].lower()

    return fancy_name, adj, verb, noun, iadj, iverb, first


def main():

    root = os.path.dirname(os.path.realpath(__file__))

    with gzip.open(root + "/dictionary.json.gz") as f:
        dict_data = json.load(f)

    cache_file_path = root + "/fancy_name_dict.json.gz"
    if os.path.isfile(cache_file_path):
        with gzip.open(cache_file_path) as f:
            word_pos_i = json.load(f)
    else:
        word_pos_i = preprocess(dict_data)
        with gzip.open(cache_file_path, "wt") as f:
            json.dump(word_pos_i, f)

    argp = ArgumentParser()
    argp.add_argument("hash", nargs="?", default=None)
    argp.add_argument("-d", "--dry-run", action="store_true")
    args = argp.parse_args()

    fancy_name, adj, verb, noun, iadj, iverb, first = compute_fancy_name(word_pos_i, hash=args.hash)

    cmd = f"git tag {fancy_name}"
    print(cmd)
    if args.hash is None and args.dry_run == False:
        os.system(cmd)

    first_meanings = []
    second_meanings = []

    for entry in dict_data:
        if entry['word'] == adj and entry['pos'] == 'a.' and iadj > iverb:
            first_meanings.append(entry['definitions'])
        if entry['word'] == verb and entry['pos'] == 'v.' and iadj <= iverb:
            first_meanings.append(entry['definitions'])
        if entry['word'] == noun and entry['pos'] == 'n.':
            second_meanings.append(entry['definitions'])
    
    pprint.pprint({
        first: first_meanings,
        noun: second_meanings, 
    })


if __name__ == "__main__":
    main()
